/**
 * 持久化存储的任务队列实现
 */

import type { BaseStorage } from '@/libs/utils/storage';
import { createStorage } from '@/libs/utils/storage';

export interface TaskQueueItem<T> {
  id: string;
  data: T;
  provider: string;
  timestamp: number;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  lastProcessedAt?: number;
}

export interface PersistentTaskQueueOptions {
  namespace: string;
  maxConcurrency?: number;
  retryDelay?: number;
}

export class PersistentTaskQueue<T> {
  private storage: BaseStorage<TaskQueueItem<T>>;

  private activeTasksCount = 0;

  private processingTaskIds = new Set<string>();

  private options: Required<PersistentTaskQueueOptions>;

  constructor(namespace: string | PersistentTaskQueueOptions) {
    // 处理兼容性：支持旧的构造函数参数
    if (typeof namespace === 'string') {
      this.options = {
        namespace,
        maxConcurrency: 5,
        retryDelay: 1000,
      };
    } else {
      this.options = {
        namespace: namespace.namespace,
        maxConcurrency: namespace.maxConcurrency || 5,
        retryDelay: namespace.retryDelay || 1000,
      };
    }

    this.storage = createStorage<TaskQueueItem<T>>({ namespace: this.options.namespace });
  }

  /**
   * 判断是否可以消费更多任务
   * @private
   */
  private canConsumeMore(): boolean {
    return this.activeTasksCount < this.options.maxConcurrency;
  }

  /**
   * 提供一个新的任务到队列中
   * @param data 任务数据
   * @param provider 提供者标识
   * @returns 任务ID
   */
  async provide(data: T, provider: string): Promise<string> {
    const id = `task_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
    const task: TaskQueueItem<T> = {
      id,
      data,
      provider,
      timestamp: Date.now(),
      status: 'pending',
    };

    await this.storage.set(id, task);
    return id;
  }

  /**
   * 消费队列中的下一个待处理任务
   * @returns 任务数据，如果没有待处理任务或达到并发限制则返回null
   */
  async consume(): Promise<{ id: string; data: T } | null> {
    // 检查并发限制
    if (!this.canConsumeMore()) {
      return null;
    }

    const allTasks = await this.storage.getAll();
    const pendingTask = allTasks.find((task) => task.status === 'pending' && !this.processingTaskIds.has(task.id));

    if (!pendingTask) {
      return null;
    }

    // 标记为正在处理
    this.processingTaskIds.add(pendingTask.id);
    this.activeTasksCount++;

    pendingTask.status = 'processing';
    pendingTask.lastProcessedAt = Date.now();
    await this.storage.set(pendingTask.id, pendingTask);

    return {
      id: pendingTask.id,
      data: pendingTask.data,
    };
  }

  /**
   * 批量消费多个任务，最多消费到达到并发限制
   * @returns 任务数据数组
   */
  async consumeMultiple(): Promise<Array<{ id: string; data: T }>> {
    const results: Array<{ id: string; data: T }> = [];

    // 计算还可以消费多少任务
    const availableSlots = Math.max(0, this.options.maxConcurrency - this.activeTasksCount);

    if (availableSlots <= 0) {
      return results;
    }

    const allTasks = await this.storage.getAll();
    const pendingTasks = allTasks
      .filter((task) => task.status === 'pending' && !this.processingTaskIds.has(task.id))
      .slice(0, availableSlots);

    // 没有待处理任务
    if (pendingTasks.length === 0) {
      return results;
    }

    // 处理所有可消费的任务，使用Promise.all避免await in loop
    const processTasks = pendingTasks.map(async (task) => {
      this.processingTaskIds.add(task.id);
      this.activeTasksCount++;

      task.status = 'processing';
      task.lastProcessedAt = Date.now();
      await this.storage.set(task.id, task);

      return {
        id: task.id,
        data: task.data,
      };
    });

    const processedResults = await Promise.all(processTasks);
    results.push(...processedResults);

    return results;
  }

  /**
   * 完成任务
   * @param id 任务ID
   * @param success 是否成功完成
   */
  async complete(id: string, success = true): Promise<void> {
    const task = await this.storage.get(id);
    if (task) {
      task.status = success ? 'completed' : 'failed';
      task.lastProcessedAt = Date.now();
      await this.storage.set(id, task);

      // 减少活跃任务计数
      this.activeTasksCount = Math.max(0, this.activeTasksCount - 1);
      this.processingTaskIds.delete(id);
    }
  }

  /**
   * 获取当前队列状态信息
   */
  async getStats() {
    const allTasks = await this.storage.getAll();

    return {
      total: allTasks.length,
      pending: allTasks.filter((t) => t.status === 'pending').length,
      processing: allTasks.filter((t) => t.status === 'processing').length,
      completed: allTasks.filter((t) => t.status === 'completed').length,
      failed: allTasks.filter((t) => t.status === 'failed').length,
      activeTasks: this.activeTasksCount,
      concurrencyLimit: this.options.maxConcurrency,
    };
  }

  /**
   * 重置所有卡住的处理中任务
   * 当任务处理时间超过指定时间时，将其重置为待处理状态
   * @param maxProcessingTime 最大处理时间（毫秒），默认为5分钟
   */
  async resetStuckTasks(maxProcessingTime = 5 * 60 * 1000): Promise<number> {
    const allTasks = await this.storage.getAll();
    const now = Date.now();

    const processingTasks = allTasks.filter(
      (task) => task.status === 'processing' && task.lastProcessedAt && now - task.lastProcessedAt > maxProcessingTime,
    );

    // 使用Promise.all避免await in loop
    await Promise.all(
      processingTasks.map(async (task) => {
        task.status = 'pending';
        await this.storage.set(task.id, task);
        this.processingTaskIds.delete(task.id);
      }),
    );

    // 重新校准活跃任务计数
    this.activeTasksCount = this.processingTaskIds.size;

    return processingTasks.length;
  }

  /**
   * 获取指定提供者的所有任务
   * @param provider 提供者标识
   * @returns 该提供者的所有任务列表
   */
  async getTasksByProvider(provider: string): Promise<TaskQueueItem<T>[]> {
    return this.storage.query((task: TaskQueueItem<T>) => task.provider === provider);
  }

  /**
   * 获取所有任务
   * @returns 所有任务的列表
   */
  async getAllTasks(): Promise<TaskQueueItem<T>[]> {
    return this.storage.getAll();
  }

  /**
   * 清理已完成的任务
   * @param maxAge 最大保留时间（毫秒），默认24小时
   */
  async cleanup(maxAge = 24 * 60 * 60 * 1000): Promise<number> {
    const allTasks = await this.storage.getAll();
    const now = Date.now();

    const expiredTasks = allTasks.filter(
      (task: TaskQueueItem<T>) =>
        (task.status === 'completed' || task.status === 'failed') && now - task.timestamp > maxAge,
    );

    if (expiredTasks.length > 0) {
      await Promise.all(expiredTasks.map((task) => this.storage.delete(task.id)));
    }

    return expiredTasks.length;
  }

  /**
   * 销毁队列实例，清理资源
   */
  destroy(): void {
    this.processingTaskIds.clear();
    this.activeTasksCount = 0;
  }
}
